package bod;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.io.IOException;

import javax.swing.JFrame;

import bod.engine.Engine;
import bod.gui.Screen;

@SuppressWarnings("serial")
public class Main extends Canvas implements Runnable {

	public static final int	ticksPerSecond	= 50;

	public static void main(String[] args) {
		Images.initialize();
		Engine.initialize();
		Main bod = new Main();
		JFrame frame = new JFrame("Border of Darkness");
		frame.setUndecorated(true);
		frame.setResizable(false);
		frame.add(bod);
		frame.pack();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		bod.start();
	}

	private Thread			thread;
	private EventHandler	eventHandler;
	private Font			font;

	public Main() {
		Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
		this.setSize(size);
		this.setPreferredSize(size);
		this.setMinimumSize(size);
		this.setMaximumSize(size);
		Screen.initialize(size.width, size.height);
		this.eventHandler = new EventHandler();
		this.addKeyListener(this.eventHandler);
		this.addMouseListener(this.eventHandler);
		this.addMouseMotionListener(this.eventHandler);
		try {
			this.font = Font.createFont(Font.TRUETYPE_FONT,
					Main.class.getResourceAsStream("/fnt/bod.ttf"));
			this.font = this.font.deriveFont(Font.TRUETYPE_FONT, 28);
		} catch (FontFormatException | IOException e) {
			e.printStackTrace();
		}
		this.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(
				Images.crsr, new Point(9, 9), "Cursor"));
	}

	private void start() {
		this.createBufferStrategy(2);
		this.requestFocus();
		this.thread = new Thread(this);
		this.thread.run();
	}

	@Override
	public void run() {
		long lastTime = System.nanoTime();
		double unprocessed = 0;
		double secondsPerTick = 1.0 / ticksPerSecond;
		int ticks = 0;
		int frames = 0;
		while (true) {
			long now = System.nanoTime();
			long time = now - lastTime;
			lastTime = now;
			if (time < 0) {
				time = 0;
			} else if (time > 1000000000) {
				time = 1000000000;
			}
			unprocessed += time / 1000000000.0;
			boolean tick = false;
			while (unprocessed > secondsPerTick) {
				this.tick();
				unprocessed -= secondsPerTick;
				tick = true;
				ticks++;
				if (ticks % ticksPerSecond == 0) {
					Screen.setFps(frames);
					lastTime += 1000;
					frames = 0;
				}
			}
			if (tick) {
				this.draw();
				frames++;
			} else {
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void tick() {
		if (Progress.isBusy()) {
			Progress.tick();
		} else {
			Engine.tick();
		}
	}

	private void draw() {
		BufferStrategy bs = this.getBufferStrategy();
		Graphics g = bs.getDrawGraphics();
		g.setFont(this.font);
		Screen.draw(g);
		g.dispose();
		bs.show();
	}

}